package com.p2l.letterblocks;

import java.util.Calendar;
import java.util.List;

import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Toast;

public class GameController implements SensorEventListener, OnTouchListener {
	private GamePersistor persistor;
	private SensorManager manager;
	private Sensor sensor;
	private MediaPlayer box, jump;
	
	private long timeStarted;
	
	public GameController(GamePersistor p) {
		this.persistor = p;
		
		manager = (SensorManager)persistor.getSystemService(Activity.SENSOR_SERVICE);
		sensor = manager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
		
		// If default sensor exist
		if (sensor != null) {
			manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
		// Else find sensor list
		} else {
			List<Sensor> sensorList = manager.getSensorList(Sensor.TYPE_ORIENTATION);
			if (sensorList.size() > 0) {
				manager.registerListener(this, sensorList.get(0), SensorManager.SENSOR_DELAY_GAME);
			} else {
				persistor.runOnUiThread(new Runnable() {
					@Override
					public void run() {
						Toast.makeText(persistor, persistor.getResources().getString(R.string.error_sensor_not_detected), Toast.LENGTH_LONG).show();
						persistor.finish();
					}
				});
			}
		}
		
		timeStarted = Calendar.getInstance().getTimeInMillis();
	}
	
	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		long currentTime = Calendar.getInstance().getTimeInMillis();
		if (persistor != null) {
			if (!persistor.loading && currentTime - timeStarted >= 2500) {
				Bear bear = persistor.getModel().getBear();
				if (bear != null && !persistor.getModel().getPause().isPaused() && !persistor.getModel().getEndLevel().isFinished()) {
					float y = GamePersistor.DEFAULT_ORIENTATION == 1 ? event.values[1] : event.values[2];
					y = (y > 2 ? 10 : y);
					y = (y < -2 ? -10 : y);
					y = (y <= 2 && y >= -2 ? 0 : y);
					bear.getVector().setX(y * (GamePersistor.SCREEN_WIDTH / Vector.SPEED));
					
					if (y != 0)
						bear.getLastKnownDirection().setX(-y / 100);
				}
			}
		}
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		long currentTime = Calendar.getInstance().getTimeInMillis();
		if (event.getAction() == MotionEvent.ACTION_DOWN && !persistor.loading && currentTime - timeStarted >= 2500) {
			float x = event.getX();
			float y = event.getY();
			
			Pause pause = persistor.getModel().getPause();
			EndLevel end = persistor.getModel().getEndLevel();
			
			if (pause.isPaused() && !end.isFinished()) {
				if (pause.getYesButton().isPressed(x, y)) {
					persistor.finish();
				} else if (pause.getNoButton().isPressed(x, y)) {
					pause.setPaused(false);
					persistor.getModel().startMusic();
				}
			} else if (end.isFinished() && end.getNextButton().isPressed(x, y) && end.getNextButton().isEnabled()) {
				persistor.finish();
			} else if (!end.isFinished()) {
				Bear bear = persistor.getModel().getBear();
				if (bear != null) {
					Button pick = persistor.getModel().getPickButton();
					Button word = persistor.getModel().getWordButton();
					
					if (pick.isEnabled() && pick.isPressed(x, y)) {
						if (bear.getBlock() == null) {
							Block[] blocks = persistor.getModel().getBlocks();
							boolean found = false;
							int i = 0;
							while (!found && i < blocks.length) {
								if (bear.isColliding(blocks[i]) && bear.getY() + bear.getHeight() > blocks[i].getY() + GameModel.FACTOR && bear.getY() - GameModel.FACTOR < blocks[i].getY() + blocks[i].getHeight()) {
									if (bear.getLastKnownDirection().getX() < 0 && bear.getX() > blocks[i].getX()) {
										found = true;
									} else if (bear.getLastKnownDirection().getX() > 0 && bear.getX() < blocks[i].getX()) {
										found = true;
									} else {
										i++;
									}
								} else {
									i++;
								}
							}
							if (found) {
								if (bear.getLastKnownDirection().getX() < 0)
									blocks[i].setX(bear.getX() - blocks[i].getWidth() + (GameModel.FACTOR * 7));
								else
									blocks[i].setX(bear.getX() + blocks[i].getWidth() - (GameModel.FACTOR * 7));
								blocks[i].setY((bear.getY() + (bear.getHeight() / 3 * 2)) - (blocks[i].getHeight() / 2));
								blocks[i].getVector().setY(0f);
								bear.setBlock(blocks[i]);
							}
						} else {
							Block b = bear.getBlock();
							bear.setX(bear.getX() + ((bear.getX() > b.getX() ? GameModel.FACTOR : -GameModel.FACTOR) * 7));
							bear.setBlock(null);
							box.start();
						}
					} else if (word.isPressed(x, y)) {
						MediaPlayer sWord = persistor.getModel().getEndLevel().getWordMediaPlayer();
						if (!sWord.isPlaying()) {
							persistor.getModel().getMusic().pause();
							sWord.start();
						}
					} else {
						// If bear is on the floor - Jump
						float bottom = GamePersistor.SCREEN_HEIGHT - bear.getHeight() - (GamePersistor.SCREEN_HEIGHT / 100 * GameView.BOTTOM);
						if (bear.getY() == bottom) {
							bear.getVector().setY(GamePersistor.SCREEN_HEIGHT / Vector.JUMP);
							jump.start();
						} else {
							Block[] blocks = persistor.getModel().getBlocks();
							boolean found = false;
							int i = 0;
							
							// If the bear collide with blocks
							while (!found && i < blocks.length) {
								Block b = blocks[i];
								if (bear.isColliding(b)) {
									// If bear is colliding from the side and not from the top
									if ((int)(bear.getY() + bear.getHeight()) == (int)b.getY() && bear.getX() < b.getX() + b.getWidth() - (GameModel.FACTOR * 2) && bear.getX() + bear.getWidth() - (GameModel.FACTOR * 2) > b.getX())
										found = true;
									else
										i++;
								} else {
									i++;
								}
							}
							
							Obstacle[] obstacles = persistor.getModel().getObstacles();
							i = 0;
							while (!found && i < obstacles.length) {
								Obstacle o = obstacles[i];
								if (bear.isColliding(o)) {
									if ((int)(bear.getY() + bear.getHeight()) == (int)o.getY() && bear.getX() < o.getX() + o.getWidth() - (GameModel.FACTOR * 2) && bear.getX() + bear.getWidth() - (GameModel.FACTOR * 2) > o.getX()) {
										found = true;
									} else {
										i++;
									}
								} else {
									i++;
								}
							}
			
							// If bear is on a box - Jump
							if (found) {
								bear.getVector().setY(GamePersistor.SCREEN_HEIGHT / Vector.JUMP);
								jump.start();
							}
						}
					}
				}
			}
			//Log.d("LetterBlocks", event.getX() + ", " + event.getY());
		}
		return false;
	}
    
    public boolean onKeyDown(int keyCode, KeyEvent event) {
		long currentTime = Calendar.getInstance().getTimeInMillis();
    	if (keyCode == KeyEvent.KEYCODE_BACK && !persistor.loading && currentTime - timeStarted >= 2500) {
    		Pause pause = persistor.getModel().getPause();
    		if (!pause.isPaused()) {
    			pause.setPaused(true);
    			persistor.getModel().pauseMusic();
    		}
    	}
    	return false;
    }
	
	public void onPause() {
		manager.unregisterListener(this);
		
		box.release();
		box = null;
		jump.release();
		jump = null;
	}
	
	public void onResume() {
		if (manager != null && sensor != null) {
			manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
		}
		
		box = MediaPlayer.create(persistor, R.raw.box);
		box.setVolume(persistor.effects, persistor.effects);
		jump = MediaPlayer.create(persistor, R.raw.jump);
		jump.setVolume(persistor.effects, persistor.effects);
	}
	
	public void onDestroy() {
		persistor = null;
		manager = null;
		sensor = null;
	}
}